package service

import (
	"fmt"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	"go-file-perception-model/internal/config"
	"go-file-perception-model/internal/logger"
	"go-file-perception-model/internal/model"

	"go.uber.org/zap"
)

// DirectoryTreeService 目录树服务
type DirectoryTreeService struct {
	fileCollector *FileCollector
	indexManager  *IndexManager
	config        *config.Config
}

// NewDirectoryTreeService 创建目录树服务实例
func NewDirectoryTreeService(fileCollector *FileCollector, indexManager *IndexManager, cfg *config.Config) *DirectoryTreeService {
	return &DirectoryTreeService{
		fileCollector: fileCollector,
		indexManager:  indexManager,
		config:        cfg,
	}
}

// GetDirectoryTree 获取目录树
func (s *DirectoryTreeService) GetDirectoryTree(req model.DirectoryTreeRequest) (*model.DirectoryTreeResponse, error) {
	startTime := time.Now()

	// 如果没有指定目录，使用配置中的索引目录
	if req.Directory == "" || req.Directory == "." {
		if len(s.config.FileIndex.IndexDirectories) > 0 {
			// 使用第一个索引目录作为默认目录
			req.Directory = s.config.FileIndex.IndexDirectories[0]
			logger.Info("Using configured index directory as default", zap.String("directory", req.Directory))
		} else {
			// 如果没有配置索引目录，使用当前目录
			req.Directory = "."
		}
	}

	// 如果没有指定目录，使用配置中的索引目录
	if req.Directory == "" || req.Directory == "." {
		if len(s.config.FileIndex.IndexDirectories) > 0 {
			// 使用第一个索引目录作为默认目录
			req.Directory = s.config.FileIndex.IndexDirectories[0]
			logger.Info("Using configured index directory for search", zap.String("directory", req.Directory))
		} else {
			// 如果没有配置索引目录，使用当前目录
			req.Directory = "."
		}
	}

	// 验证目录是否存在
	if _, err := os.Stat(req.Directory); os.IsNotExist(err) {
		return nil, fmt.Errorf("directory does not exist: %s", req.Directory)
	}

	// 设置默认值
	if req.MaxDepth <= 0 {
		req.MaxDepth = 100 // 默认最大深度
	}

	// 构建目录树
	root, stats, err := s.buildDirectoryTree(req.Directory, req, 0)
	if err != nil {
		return nil, fmt.Errorf("failed to build directory tree: %w", err)
	}

	// 应用过滤器
	if req.FileFilter != "" {
		filteredRoot, filteredStats := s.applyFilter(root, req.FileFilter, req.OnlyIndexed)
		root = filteredRoot
		stats.FileNodes = filteredStats.FileNodes
		stats.DirNodes = filteredStats.DirNodes
		stats.IndexedNodes = filteredStats.IndexedNodes
	}

	took := time.Since(startTime).Milliseconds()

	return &model.DirectoryTreeResponse{
		Root:          root,
		TotalFiles:    stats.FileNodes,
		TotalDirs:     stats.DirNodes,
		IndexedFiles:  stats.IndexedNodes,
		FilteredFiles: stats.FileNodes,
		Took:          took,
	}, nil
}

// SearchDirectoryTree 搜索目录树
func (s *DirectoryTreeService) SearchDirectoryTree(req model.DirectoryTreeSearchRequest) (*model.DirectoryTreeResponse, error) {
	startTime := time.Now()

	// 验证目录是否存在
	if _, err := os.Stat(req.Directory); os.IsNotExist(err) {
		return nil, fmt.Errorf("directory does not exist: %s", req.Directory)
	}

	// 设置默认值
	if req.MaxDepth <= 0 {
		req.MaxDepth = 100
	}
	if req.SearchType == "" {
		req.SearchType = "filename"
	}

	// 构建目录树
	root, stats, err := s.buildDirectoryTree(req.Directory, req.DirectoryTreeRequest, 0)
	if err != nil {
		return nil, fmt.Errorf("failed to build directory tree: %w", err)
	}

	// 应用搜索过滤
	filteredRoot, filteredStats := s.applySearchFilter(root, req)

	took := time.Since(startTime).Milliseconds()

	return &model.DirectoryTreeResponse{
		Root:          filteredRoot,
		TotalFiles:    stats.FileNodes,
		TotalDirs:     stats.DirNodes,
		IndexedFiles:  stats.IndexedNodes,
		FilteredFiles: filteredStats.FileNodes,
		Took:          took,
	}, nil
}

// buildDirectoryTree 递归构建目录树
func (s *DirectoryTreeService) buildDirectoryTree(dirPath string, req model.DirectoryTreeRequest, currentDepth int) (*model.DirectoryTreeNode, *model.DirectoryTreeStats, error) {
	// 检查深度限制
	if req.MaxDepth > 0 && currentDepth >= req.MaxDepth {
		return nil, nil, nil
	}

	// 获取目录信息
	info, err := os.Stat(dirPath)
	if err != nil {
		return nil, nil, err
	}

	// 创建根节点
	node := &model.DirectoryTreeNode{
		Name:       filepath.Base(dirPath),
		Path:       dirPath,
		Type:       "directory",
		Size:       0,
		ModTime:    info.ModTime(),
		IsIndexed:  s.isDirectoryIndexed(dirPath),
		Children:   make([]*model.DirectoryTreeNode, 0),
		Depth:      currentDepth,
		IsExpanded: currentDepth < 2, // 默认展开前两层
	}

	// 如果是根目录，使用完整路径作为名称
	if currentDepth == 0 {
		node.Name = dirPath
	}

	// 统计信息
	stats := &model.DirectoryTreeStats{
		TotalNodes:   1,
		DirNodes:     1,
		FileNodes:    0,
		IndexedNodes: 0,
		MaxDepth:     currentDepth,
		FileTypes:    make(map[string]int),
		SizeByType:   make(map[string]int64),
		LastScanned:  time.Now(),
	}

	if node.IsIndexed {
		stats.IndexedNodes++
	}

	// 读取目录内容
	entries, err := os.ReadDir(dirPath)
	if err != nil {
		logger.Warn("Failed to read directory", zap.String("path", dirPath), zap.Error(err))
		return node, stats, nil
	}

	// 处理每个条目
	for _, entry := range entries {
		entryPath := filepath.Join(dirPath, entry.Name())

		// 跳过隐藏文件（如果设置了不显示）
		if !req.ShowHidden && strings.HasPrefix(entry.Name(), ".") {
			continue
		}

		entryInfo, err := entry.Info()
		if err != nil {
			logger.Warn("Failed to get entry info", zap.String("path", entryPath), zap.Error(err))
			continue
		}

		if entry.IsDir() {
			// 递归处理子目录
			childNode, childStats, err := s.buildDirectoryTree(entryPath, req, currentDepth+1)
			if err != nil {
				logger.Warn("Failed to build child directory tree", zap.String("path", entryPath), zap.Error(err))
				continue
			}

			if childNode != nil {
				node.Children = append(node.Children, childNode)

				// 合并统计信息
				stats.TotalNodes += childStats.TotalNodes
				stats.DirNodes += childStats.DirNodes
				stats.FileNodes += childStats.FileNodes
				stats.IndexedNodes += childStats.IndexedNodes
				if childStats.MaxDepth > stats.MaxDepth {
					stats.MaxDepth = childStats.MaxDepth
				}

				// 合并文件类型统计
				for fileType, count := range childStats.FileTypes {
					stats.FileTypes[fileType] += count
				}
				for fileType, size := range childStats.SizeByType {
					stats.SizeByType[fileType] += size
				}
			}
		} else {
			// 处理文件
			fileNode := &model.DirectoryTreeNode{
				Name:       entry.Name(),
				Path:       entryPath,
				Type:       "file",
				Size:       entryInfo.Size(),
				Extension:  strings.ToLower(filepath.Ext(entry.Name())),
				ModTime:    entryInfo.ModTime(),
				IsIndexed:  s.isFileIndexed(entryPath),
				Children:   nil,
				Depth:      currentDepth + 1,
				IsExpanded: false,
			}

			// 检查文件是否符合索引条件
			if req.OnlyIndexed && !fileNode.IsIndexed {
				continue
			}

			node.Children = append(node.Children, fileNode)

			// 更新统计信息
			stats.TotalNodes++
			stats.FileNodes++
			if fileNode.IsIndexed {
				stats.IndexedNodes++
			}

			// 文件类型统计
			ext := fileNode.Extension
			if ext == "" {
				ext = "no_extension"
			}
			stats.FileTypes[ext]++
			stats.SizeByType[ext] += fileNode.Size
		}
	}

	// 对子节点排序：目录在前，文件在后，同类型按名称排序
	sort.Slice(node.Children, func(i, j int) bool {
		if node.Children[i].Type != node.Children[j].Type {
			return node.Children[i].Type == "directory"
		}
		return strings.ToLower(node.Children[i].Name) < strings.ToLower(node.Children[j].Name)
	})

	return node, stats, nil
}

// applyFilter 应用文件名过滤器
func (s *DirectoryTreeService) applyFilter(node *model.DirectoryTreeNode, filter string, onlyIndexed bool) (*model.DirectoryTreeNode, *model.DirectoryTreeStats) {
	if node == nil {
		return nil, &model.DirectoryTreeStats{}
	}

	// 编译正则表达式
	regex, err := regexp.Compile(filter)
	if err != nil {
		logger.Warn("Invalid regex pattern, using literal match", zap.String("pattern", filter), zap.Error(err))
		// 如果正则表达式无效，使用字面量匹配
		regex = nil
	}

	stats := &model.DirectoryTreeStats{
		FileTypes:  make(map[string]int),
		SizeByType: make(map[string]int64),
	}

	filteredNode := &model.DirectoryTreeNode{
		Name:       node.Name,
		Path:       node.Path,
		Type:       node.Type,
		Size:       node.Size,
		Extension:  node.Extension,
		ModTime:    node.ModTime,
		IsIndexed:  node.IsIndexed,
		Children:   make([]*model.DirectoryTreeNode, 0),
		Depth:      node.Depth,
		IsExpanded: node.IsExpanded,
	}

	// 处理子节点
	for _, child := range node.Children {
		if child.Type == "directory" {
			// 递归处理目录
			filteredChild, childStats := s.applyFilter(child, filter, onlyIndexed)
			if filteredChild != nil && (len(filteredChild.Children) > 0 || s.matchesFilter(filteredChild, regex, filter)) {
				filteredNode.Children = append(filteredNode.Children, filteredChild)

				// 合并统计信息
				stats.FileNodes += childStats.FileNodes
				stats.DirNodes += childStats.DirNodes
				stats.IndexedNodes += childStats.IndexedNodes
				for fileType, count := range childStats.FileTypes {
					stats.FileTypes[fileType] += count
				}
				for fileType, size := range childStats.SizeByType {
					stats.SizeByType[fileType] += size
				}
			}
		} else {
			// 处理文件
			if s.matchesFilter(child, regex, filter) && (!onlyIndexed || child.IsIndexed) {
				filteredNode.Children = append(filteredNode.Children, child)

				// 更新统计信息
				stats.FileNodes++
				if child.IsIndexed {
					stats.IndexedNodes++
				}

				ext := child.Extension
				if ext == "" {
					ext = "no_extension"
				}
				stats.FileTypes[ext]++
				stats.SizeByType[ext] += child.Size
			}
		}
	}

	// 如果是目录且有子节点，则包含该目录
	if filteredNode.Type == "directory" && len(filteredNode.Children) > 0 {
		stats.DirNodes++
		if filteredNode.IsIndexed {
			stats.IndexedNodes++
		}
	}

	return filteredNode, stats
}

// applySearchFilter 应用搜索过滤器
func (s *DirectoryTreeService) applySearchFilter(node *model.DirectoryTreeNode, req model.DirectoryTreeSearchRequest) (*model.DirectoryTreeNode, *model.DirectoryTreeStats) {
	if node == nil {
		return nil, &model.DirectoryTreeStats{}
	}

	// 编译正则表达式
	var regex *regexp.Regexp
	var err error

	pattern := req.Pattern
	if !req.CaseSensitive {
		pattern = "(?i)" + pattern // 添加不区分大小写标志
	}

	regex, err = regexp.Compile(pattern)
	if err != nil {
		logger.Warn("Invalid regex pattern, using literal match", zap.String("pattern", req.Pattern), zap.Error(err))
		regex = nil
	}

	stats := &model.DirectoryTreeStats{
		FileTypes:  make(map[string]int),
		SizeByType: make(map[string]int64),
	}

	filteredNode := &model.DirectoryTreeNode{
		Name:       node.Name,
		Path:       node.Path,
		Type:       node.Type,
		Size:       node.Size,
		Extension:  node.Extension,
		ModTime:    node.ModTime,
		IsIndexed:  node.IsIndexed,
		Children:   make([]*model.DirectoryTreeNode, 0),
		Depth:      node.Depth,
		IsExpanded: node.IsExpanded,
	}

	// 处理子节点
	for _, child := range node.Children {
		if child.Type == "directory" {
			// 递归处理目录
			filteredChild, childStats := s.applySearchFilter(child, req)
			if filteredChild != nil && (len(filteredChild.Children) > 0 || s.matchesSearchFilter(filteredChild, req, regex)) {
				filteredNode.Children = append(filteredNode.Children, filteredChild)

				// 合并统计信息
				stats.FileNodes += childStats.FileNodes
				stats.DirNodes += childStats.DirNodes
				stats.IndexedNodes += childStats.IndexedNodes
				for fileType, count := range childStats.FileTypes {
					stats.FileTypes[fileType] += count
				}
				for fileType, size := range childStats.SizeByType {
					stats.SizeByType[fileType] += size
				}
			}
		} else {
			// 处理文件
			if s.matchesSearchFilter(child, req, regex) && (!req.OnlyIndexed || child.IsIndexed) {
				filteredNode.Children = append(filteredNode.Children, child)

				// 更新统计信息
				stats.FileNodes++
				if child.IsIndexed {
					stats.IndexedNodes++
				}

				ext := child.Extension
				if ext == "" {
					ext = "no_extension"
				}
				stats.FileTypes[ext]++
				stats.SizeByType[ext] += child.Size
			}
		}
	}

	// 如果是目录且有子节点，则包含该目录
	if filteredNode.Type == "directory" && len(filteredNode.Children) > 0 {
		stats.DirNodes++
		if filteredNode.IsIndexed {
			stats.IndexedNodes++
		}
	}

	return filteredNode, stats
}

// matchesFilter 检查节点是否匹配过滤器
func (s *DirectoryTreeService) matchesFilter(node *model.DirectoryTreeNode, regex *regexp.Regexp, filter string) bool {
	if regex != nil {
		return regex.MatchString(node.Name)
	}

	// 使用字面量匹配（不区分大小写）
	return strings.Contains(strings.ToLower(node.Name), strings.ToLower(filter))
}

// matchesSearchFilter 检查节点是否匹配搜索过滤器
func (s *DirectoryTreeService) matchesSearchFilter(node *model.DirectoryTreeNode, req model.DirectoryTreeSearchRequest, regex *regexp.Regexp) bool {
	var target string

	switch req.SearchType {
	case "filename":
		target = node.Name
	case "path":
		target = node.Path
	case "extension":
		target = node.Extension
	default:
		target = node.Name
	}

	if regex != nil {
		return regex.MatchString(target)
	}

	// 使用字面量匹配
	pattern := req.Pattern
	if !req.CaseSensitive {
		target = strings.ToLower(target)
		pattern = strings.ToLower(pattern)
	}

	return strings.Contains(target, pattern)
}

// isFileIndexed 检查文件是否已被索引
func (s *DirectoryTreeService) isFileIndexed(filePath string) bool {
	if s.indexManager == nil {
		return false
	}

	// 这里可以调用索引管理器的方法来检查文件是否已被索引
	// 暂时返回false，实际实现需要根据索引管理器的接口来调整
	return false
}

// isDirectoryIndexed 检查目录是否在索引目录列表中
func (s *DirectoryTreeService) isDirectoryIndexed(dirPath string) bool {
	if s.indexManager == nil {
		return false
	}

	// 这里可以调用索引管理器的方法来检查目录是否在索引列表中
	// 暂时返回false，实际实现需要根据索引管理器的接口来调整
	return false
}
